package logs

import (
	"fmt"
	"time"
	"runtime"
	"errors"
	"strings"
	"path/filepath"
)


var Logger *Log


//空log, 防止以后需要包其他第三方log包
type Log struct {

}

//log的实例化方法
//返回实例化log指针
func NewLog() *Log {
	return &Log{}
}


var defaultLevel int

var logLevel =  map[string]int{
	"DEBUG":1,
	"INFO":2,
	"WARN":3,
	"ERROR":4,
	"PANIC":5,

}

func SetLevel(def int)  {
	defaultLevel = def
}



//日志内容
// fileName 文件名字
// line 调用行号
// fullPath 文件全路径
// funcName 那个方法进行调用
type logContext struct {
	fileName  string
	line      int
	fullPath string
	funcName  string
}


//打印
// skip=0  runtime.Caller 的调用者.
// skip=1  runtime/proc.c 的 runtime.main
// skip=2  runtime/proc.c 的 runtime.goexit
//
//Go的普通程序的启动顺序:
//1.runtime.goexit 为真正的函数入口(并不是main.main)
//2.然后 runtime.goexit 调用 runtime.main 函数
//3.最终 runtime.main 调用用户编写的 main.main 函数
func callerInfo(skip int) (ctx *logContext, err error)  {
	pc, file, line, ok := runtime.Caller(skip)
	if !ok {
		return nil, errors.New("error  during runtime.Callers")
	}

	funcInfo := runtime.FuncForPC(pc)
	if funcInfo == nil {
		return nil, errors.New("error during runtime.FuncForPC")
	}

	funcName := funcInfo.Name()
	if strings.HasPrefix(funcName, ".") {
		funcName = funcName[strings.Index(funcName, "."):]
	}

	ctx = &logContext{
		funcName:  filepath.Base(funcName),
		line:      line,
		fullPath:  file,
		fileName:  filepath.Base(file),
	}

	return ctx, nil

}

func write(level string, message string)  {

	if logLevel[level] <= defaultLevel {
		return
	}
	
	skip := 3
	ctx, err := callerInfo(skip)
	if err != nil {
		fmt.Println("log println err! "+ time.Now().Format("2006-01-02 15:04:05") + " Error: " +err.Error())
	}

	fmt.Println(fmt.Sprintf("[%s] %s [%s:%v] %s", level, time.Now().Format("2006-01-02 15:04:05"), ctx.fileName, ctx.line, message))
}

func(l *Log) Debug(message string)  {
	write("DEBUG", message)
}

func(l *Log)  Info(message string)  {
	write("INFO", message)
}

func(l *Log)  Warn(message string)  {
	write("WARN", message)
}

func(l *Log)  Error(message string)  {
	write("ERROR", message)
}

func(l *Log)  Panic(message string)  {
	write("PANIC", message)
}

func(l *Log)  Println(level string, message string)  {
	write(level, message)
}

func(l *Log) SysErr(err error)  {
	fmt.Println("---- begin sys error ----")
	fmt.Println(fmt.Sprintf("[%s] %s", "SYSERR", time.Now().Format("2006-01-02 15:04:05")))
	fmt.Println(err)
	fmt.Println("---- end sys error ----")
}